/**
 * 
 */
package com.gragra.nounIdentification;
import java.io.BufferedWriter;
import java.io.IOException;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntSet;
import com.gragra.data.Corpus;
import com.gragra.sampling.sequentialStructure.WordAndTagHolder;
import com.gragra.sequentiaDataGenerator.BaseGenerator;
/**
 * This class extends the BaseNounIdentifier to give implementations of the abstract methods based on interfaces that
 * can be used to specify behaviour
 * @author Christoph Teichmann
 * created Mar 25, 2013 10:41:55 PM
 * @version 0.1
 */
public class NounIdentifier extends BaseNounIdentifier
{
	/**
	 * 
	 */
	private final Corpus<WordAndTagHolder> data;
	/**
	 * an implementation of MaxAssessment is used to determine how many frames and words should be generated in
	 * each round of inference
	 */
	private final MaxAssessment ma;
	/**
	 * an implementation of ConvergenceAssessment is used determine wheter the algorithm has converged
	 */
	private final ConvergenceAssessment ca;
	/**
	 * 
	 */
	private final Scorer score;
	/**
	 * This creates a new instance, that will use the statistics from the given data, with the given amount 
	 * of post- and pre-marking and the given frameSize, the scorer will be used for ranking frame and word
	 * candidates, the ConvergenceAssessment will be used to decice when to stop and the MaxAssessment will
	 * be used to decide how many words and frames will be generated in each run
	 * @param data
	 * @param frameSize
	 * @param preMarkers
	 * @param postMarkers
	 */
	public NounIdentifier(Corpus<WordAndTagHolder> data,
			int frameSize, int preMarkers, int postMarkers, Scorer sco, ConvergenceAssessment ca, MaxAssessment ma)
	{
		super(data, frameSize, preMarkers, postMarkers);
		this.data = data;
		this.score = sco;
		this.ca = ca;
		this.ma = ma;
	}
	/* (non-Javadoc)
	 * @see com.gragra.nounIdentification.BaseNounIdentifier#maxNouns(int)
	 */
	@Override
	protected int maxNouns(int iteration)
	{return ma.getMaxNouns(iteration,this);}
	/* (non-Javadoc)
	 * @see com.gragra.nounIdentification.BaseNounIdentifier#sortWordsByScore(it.unimi.dsi.fastutil.ints.IntSet)
	 */
	@Override
	protected IntList sortWordsByScore(IntSet frames2,int iteration)
	{return score.sortWords(this.getSg().getAllWords(),this.getSg(),frames2,iteration);}
	/* (non-Javadoc)
	 * @see com.gragra.nounIdentification.BaseNounIdentifier#maxFrames(int)
	 */
	@Override
	protected int maxFrames(int iteration)
	{return ma.getMaxFrames(iteration,this);}
	/* (non-Javadoc)
	 * @see com.gragra.nounIdentification.BaseNounIdentifier#sortFramesByScore(it.unimi.dsi.fastutil.ints.IntSet)
	 */
	@Override
	protected IntList sortFramesByScore(IntSet restriction,int iteration)
	{return score.sortFrames(this.getSg().getAllFrames(),this.getSg(),restriction,iteration);}
	/* (non-Javadoc)
	 * @see com.gragra.nounIdentification.BaseNounIdentifier#hasConverged(int)
	 */
	@Override
	protected boolean hasConverged(int iterations)
	{return this.ca.hasConverged(iterations,this);}
	/**
	 * this method can be used to calculate how many word types are covered by the words currently proposed
	 * @return
	 */
	public double calculateWordTypeCoverage()
	{return ((double) this.nouns.size()) / ((double) this.getSg().getAllWords().size());}
	/**
	 * this method can be used to determine the number of words currently assigned to the class of interest
	 * @return
	 */
	public int numberOfWords()
	{return this.nouns.size();}
	/**
	 * this method can be used to determine the number of frames currently assigned to the class of interest
	 * @return
	 */
	public int numberOfFrames()
	{return this.frames.size();}
	/**
	 * 
	 */
	public void annotateSelfFrames()
	{this.annotateCorpusFrames(this.data);}
	/**
	 * 
	 */
	public void annotateSelfWords()
	{this.annotateCorpusWords(this.data);}
	/**
	 * @throws IOException 
	 * 
	 */
	public void writeOutData(BufferedWriter bw) throws IOException
	{
		boolean first = true;
		for(WordAndTagHolder wta : this.data)
		{
			if(first)
			{first = false;}
			else
			{bw.newLine();}
			bw.write(BaseGenerator.transferToString(wta));
		}
		bw.flush();
	}
}